/**
 * traveling.js
 * Copyright (C) 2007-2011 Tommi Rautava
 * 
 * This file is part of Popmungo.
 *
 * Popmungo is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 * 
 * Popmungo is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

org.mozdev.popmungo.traveling = {

	ROUTE_NAME_REGEXP: /^\s*(.*?)\s*$/,

	CITY_NAME_REGEXP: /^\s*(.*?)\,/i,
	
	BUS_STATION_LINK_ON_CAREER_PAGE_XPATH:
		"/html/body/table[3]/tbody/tr/td[1]/table[2]/tbody/tr/td/table/tbody/tr/td[2]/table[1]/tbody/tr[1]/td[2]/a[1]",
	
	ROUTE_NAME_TARGET_ON_HIGHWAY_LOCALE_PAGE_XPATH:
		'/html/body/table[3]/tbody/tr[1]/td/table/tbody/tr/td[1]/div/br[1]',
		
	LOCALE_ID_REGEXP: /[&?]LocaleID=(\d+)/i,
	
	HOURS_ON_ROUTE_NAME: /[\(\ \/](\d+)h/,
	
	LOCALE_XPATH: '/html/body/table[3]/tbody/tr/td[1]//a[contains(@href, "Locale.asp")]',
	
	LAST_TRANSPORT_ROW_XPATH: "//div[@id='transports']//tr[last()]",
	
	DATE_TIME_AND_CITY_NAME_ON_TRANSPORT_ROW_REGEXP: /(\d+[\.\-\/]\d+[\.\-\/]\d+)\s+(\d+[\.\:]\d+)\s+(.+)/,
	
	FROM_LOCALE_ID_NAME: 'FromLocaleID',
	
	TO_LOCALE_ID_NAME: 'ToLocaleID',
	
	TOUR_FORM_NAME: 'TourForm',
	
	MOVING_DATE_NAME: 'MovingDate',
	
	MOVING_TIME_NAME: 'MovingTime',

	
	addTravelTimesOnTransportPage:
	function addTravelTimesOnTransportPage(aDocument) {
		try {
			var autoSelectTransportStartCityEnabled = org.mozdev.popmungo.prefs.isEnabled("extensions.popmungo.options.traveling.autoSelectTransportStartCity");
			var autoSelectTransportStartTimeEnabled =org.mozdev.popmungo.prefs.isEnabled("extensions.popmungo.options.traveling.autoSelectTransportStartTime");
			
			if (!(autoSelectTransportStartCityEnabled ||
				autoSelectTransportStartTimeEnabled)) {
				return;
			}			

			var fromLocaleId = aDocument.getElementsByName('FromLocaleID').item(0);
			
			org.mozdev.popmungo.logger.debug('From locale ID='+ fromLocaleId.value);
			
			if (fromLocaleId.value == '0') {
				org.mozdev.popmungo.Charts.PrepareCities(aDocument);
				org.mozdev.popmungo.travelRoutes.initRouteDataByCities();
				if (autoSelectTransportStartCityEnabled) this.autoSelectTransportStartCity(aDocument);
			}
			else {
				if (autoSelectTransportStartTimeEnabled) this.autoSelectTransportDateAndTime(aDocument);
			}
		}
		catch (err) {
			org.mozdev.popmungo.logger.logError(err);
		}
	},	
	
	
	addRouteInfoOnCityPage:
	function addRouteInfoOnCityPage(aDocument) {
		try {
			var menu13 = aDocument.getElementById('Menu13');
			
			if (menu13) {
				var aNodes = menu13.getElementsByTagName('a');
				
				org.mozdev.popmungo.logger.debug('nodes='+ aNodes.length);
				
				this.replaceWithLocalizedRouteName(aDocument, aNodes);
			}
		}
		catch (err) {
			org.mozdev.popmungo.logger.logError(err);
		}		
	},


	replaceWithLocalizedRouteNameOnPage:
	function replaceWithLocalizedRouteNameOnPage(aDocument) {
		try {
			var snapshotNodes = org.mozdev.popmungo.commonFunctions.XPathOrderedSnapshot(this.LOCALE_XPATH, aDocument);
			
			org.mozdev.popmungo.logger.debug('nodes='+ snapshotNodes.snapshotLength);
			
			this.replaceWithLocalizedRouteName(aDocument, snapshotNodes);

		}
		catch (err) {
			org.mozdev.popmungo.logger.logError(err);
		}		
	},


	addLocalizedRouteNameToTitle:
	function addLocalizedRouteNameToTitle(aDocument, aNodes) {
		try {
			var addTravelTime = org.mozdev.popmungo.prefs.isEnabled("extensions.popmungo.options.traveling.addTravelTimes");
			var addLocalizedRouteName = org.mozdev.popmungo.prefs.isEnabled("extensions.popmungo.options.traveling.addLocalizedRouteName");
		
			if (addLocalizedRouteName) {
				if (!org.mozdev.popmungo.Charts.PrepareCities(aDocument)) {
					org.mozdev.popmungo.logger.debug('City information not available');
					addLocalizedRouteName = false;
				}
			}
			
			if (!addTravelTime && !addLocalizedRouteName) {
				return;
			}

			for (var i = (aNodes.length || aNodes.snapshotLength) - 1; i > -1; i--) {
				var node = aNodes.length ? aNodes.item(i) : aNodes.snapshotItem(i);
					
				if (addLocalizedRouteName) {
					var matchResult = node.search.match(this.LOCALE_ID_REGEXP);
	
					if (matchResult) {
						var localeId = matchResult[1];

						var routeData = org.mozdev.popmungo.travelRoutes.ROUTE_DATA_BY_LOCALE_ID[localeId];
			
						if (routeData) {
							var routeText = this.getLocalizedRouteName(routeData);
							
							if (addTravelTime) {
								routeText = routeText + ' ('+ routeData.travelTime +'h)';
							}
							
							if (node.title) {
								node.title = routeText +': '+ node.title;
							}							
							else {
								node.title = routeText;
							}
						}						
					}
				}
				else if (addTravelTime) {
					if (!this.isTravelTimeEmbedded(node.textContent)) {
						var hours = this.getTravelTimeByRouteLink(node);
						
						if (hours) {
							node.appendChild(aDocument.createTextNode('\u00a0('+ hours +'h)'));
						}
					}
				}
			}
		}		
		catch (err) {
			org.mozdev.popmungo.logger.logError(err);
		}		
	},


	replaceWithLocalizedRouteName:
	function replaceWithLocalizedRouteName(aDocument, aNodes) 
	{
		try {
			var addTravelTime = org.mozdev.popmungo.prefs.isEnabled("extensions.popmungo.options.traveling.addTravelTimes");
			var addLocalizedRouteName = org.mozdev.popmungo.prefs.isEnabled("extensions.popmungo.options.traveling.addLocalizedRouteName");
		
			if (addLocalizedRouteName) {
				if (!org.mozdev.popmungo.Charts.PrepareCities(aDocument)) {
					org.mozdev.popmungo.logger.debug('City information not available');
					addLocalizedRouteName = false;
				}
			}
			
			if (!addTravelTime && !addLocalizedRouteName) {
				return;
			}

			for (var i = (aNodes.length || aNodes.snapshotLength) - 1; i > -1; i--) {
				var node = aNodes.length ? aNodes.item(i) : aNodes.snapshotItem(i);
				
				if (addLocalizedRouteName) {
					var matchResult = node.search.match(this.LOCALE_ID_REGEXP);
	
					if (matchResult) {
						var localeId = matchResult[1];

						var routeData = org.mozdev.popmungo.travelRoutes.ROUTE_DATA_BY_LOCALE_ID[localeId];
			
						if (routeData) {
							var span1 = this.getLocalizedRouteNameOnSpan(aDocument, routeData);
							
							if (span1) {
								if (addTravelTime) {
									var travelTimeText = aDocument.createTextNode(
										' ('+ routeData.travelTime +'h)');
		
									span1.appendChild(travelTimeText);
								}
								
								node.innerHTML = '';
								node.appendChild(span1);
							}
						}						
					}
				}
				else if (addTravelTime) {
					if (!this.isTravelTimeEmbedded(node.textContent)) {
						var hours = this.getTravelTimeByRouteLink(node);
						
						if (hours) {
							node.appendChild(aDocument.createTextNode('\u00a0('+ hours +'h)'));
						}
					}
				}
			}
		}
		catch (err) {
			org.mozdev.popmungo.logger.logError(err);
		}		
	},
	

	addRouteInfoOnHighwayLocalePage:
	function addRouteInfoOnHighwayLocalePage(aDocument) {
		try {
			var matchResult = aDocument.location.search.match(this.LOCALE_ID_REGEXP);

			if (matchResult) {
				var addTravelTime = org.mozdev.popmungo.prefs.isEnabled("extensions.popmungo.options.traveling.addTravelTimes");
				var addLocalizedRouteName = org.mozdev.popmungo.prefs.isEnabled("extensions.popmungo.options.traveling.addLocalizedRouteName");
			
				if (!addTravelTime && !addLocalizedRouteName) {
					return;
				}

				if (!org.mozdev.popmungo.Charts.PrepareCities(aDocument)) {
					org.mozdev.popmungo.logger.debug('City information not available');
					return;
				}

				org.mozdev.popmungo.logger.debug('localeID='+ matchResult[1]);
						
				var localeId = parseInt(matchResult[1]);
				var routeData = org.mozdev.popmungo.travelRoutes.ROUTE_DATA_BY_LOCALE_ID[localeId];
	
				if (routeData) {
					var targetNode = org.mozdev.popmungo.commonFunctions.XPathFirstNode(this.ROUTE_NAME_TARGET_ON_HIGHWAY_LOCALE_PAGE_XPATH, aDocument);
						
					if (targetNode) {
						var pn = targetNode.parentNode;

						if (addLocalizedRouteName) {
							var span1 = this.getLocalizedRouteNameOnSpan(
								aDocument, routeData);
							
							if (span1) {
								if (addTravelTime) {
									var travelTimeText = aDocument.createTextNode(
										' ('+ routeData.travelTime +'h)');
		
									span1.appendChild(travelTimeText);
								}

								var br1 = aDocument.createElement('br');
								pn.insertBefore(br1, targetNode);
								pn.insertBefore(span1, targetNode);
							}
						}
						else {
							if (addTravelTime) {
								var travelTimeText = aDocument.createTextNode(
									' ('+ routeData.travelTime +'h)');
	
								pn.insertBefore(travelTimeText, targetNode);
							}
						}						
					}
					else {
						org.mozdev.popmungo.logger.debug('Unable to locate the target node');
						return;
					}
					
				}
				else { 
					org.mozdev.popmungo.logger.debug('Not a route');
					return; // Not a route (or a new route).
				}
			}
			else {
				org.mozdev.popmungo.logger.debug('No locale ID available');
				return; // No locale ID available.
			}
		}
		catch (err) {
			org.mozdev.popmungo.logger.logError(err);
		}		
	},


	getLocalizedRouteName:
	function getLocalizedRouteName(routeData) {
		try {
			var fromCityName = org.mozdev.popmungo.Charts.GetCityNameById(routeData.from);
			var toCityName = org.mozdev.popmungo.Charts.GetCityNameById(routeData.to);
			
			if (fromCityName && toCityName) {
				var routeName = fromCityName +' - '+ toCityName;
				return routeName;
			}			
		}
		catch (err) {
			org.mozdev.popmungo.logger.logError(err);
		}
		
		return undefined;
	},


	getLocalizedRouteNameOnSpan: 
	function getLocalizedRouteNameOnSpan(aDocument, routeData) {
		try {
			var routeName = this.getLocalizedRouteName(routeData);
			
			if (routeName) {
				var span1 = aDocument.createElement('span');
				span1.appendChild(aDocument.createTextNode(routeName));
				span1.className = 'popmungo_route';
				
				return span1;
			}		
		}
		catch (err) {
			org.mozdev.popmungo.logger.logError(err);
		}
		
		return null;
	},
		
	
	isTravelTimeEmbedded:
	function isTravelTimeEmbedded(routeName) {
		try {
			var res = routeName.match(this.HOURS_ON_ROUTE_NAME);

			if (res) {
				return res[1];
			}			
		}
		catch (err) {
			org.mozdev.popmungo.logger.logError(err);
		}
		
		return false;	
	},
	

	getTravelTimeByCities: function getTravelTimeByCities(city1Id, city2Id) {
		try {
			var routeData = org.mozdev.popmungo.travelRoutes.ROUTE_DATA_BY_CITIES[city1Id][city2Id];

			return routeData ? routeData.travelTime : undefined;
		}
		catch (err) {
			org.mozdev.popmungo.logger.logError(err);
		}

		return undefined;			
	},
	
	
	getTravelTimeByRouteLink: 
	function getTravelTimeByRouteLink(node) {
		try {
			var matchResult = node.href.match(this.LOCALE_ID_REGEXP);
			
			if (matchResult) {
				var localeId = matchResult[1];
				
				var routeData = org.mozdev.popmungo.travelRoutes.ROUTE_DATA_BY_LOCALE_ID[localeId];
				
				return routeData ? routeData.travelTime : undefined;
			}			
		}	
		catch (err) {
			org.mozdev.popmungo.logger.logError(err);
		}
		
		return undefined;
	},
	
	
	autoSelectTransportStartCity:
	function autoSelectTransportStartCity(aDocument) {
		try {
			if (!org.mozdev.popmungo.prefs.isEnabled("extensions.popmungo.options.traveling.autoSelectTransportStartCity")) {
				return;
			}
			
			var lastRow = org.mozdev.popmungo.commonFunctions.XPathFirstNode(this.LAST_TRANSPORT_ROW_XPATH, aDocument);

			if (!lastRow) {
				return;
			}

			org.mozdev.popmungo.logger.debug(lastRow);

			var td1 = lastRow.cells.item(0);
			
			var dataMatch = td1.textContent.match(this.DATE_TIME_AND_CITY_NAME_ON_TRANSPORT_ROW_REGEXP);
			org.mozdev.popmungo.logger.debug(td1.textContent);
			
			if (dataMatch && dataMatch.length > 1) {
				//var endDate = org.mozdev.popmungo.commonFunctions.trim(dataMatch[1]);
				//var endTime = org.mozdev.popmungo.commonFunctions.trim(dataMatch[2]);
				var city = org.mozdev.popmungo.commonFunctions.trim(dataMatch[3]);
				
				org.mozdev.popmungo.logger.debug('city='+ city);
			
				var opt;
				var fromLocaleId = aDocument.getElementsByName(this.FROM_LOCALE_ID_NAME).item(0);
				
				for (var i = fromLocaleId.options.length - 1; i > -1; i--) {
					opt = fromLocaleId.options.item(i);
					
					//org.mozdev.popmungo.logger.debug(i +': fromLocaleId.text='+ opt.text);

					if (opt.text.match(city)) {
						org.mozdev.popmungo.logger.debug('fromLocaleId.selectedIndex='+ i);
						
						fromLocaleId.selectedIndex = i;

						break;
					}
				}

				aDocument.getElementsByName(this.TO_LOCALE_ID_NAME).item(0).disabled = true;
				aDocument.getElementsByName(this.MOVING_DATE_NAME).item(0).disabled = true;
				aDocument.getElementsByName(this.MOVING_TIME_NAME).item(0).disabled = true;

				if (org.mozdev.popmungo.prefs.isEnabled("extensions.popmungo.options.traveling.autoSubmitTransportStartCity")) {
					var tourForm = aDocument.getElementsByName(this.TOUR_FORM_NAME).item(0);
	
					if (tourForm) {
						org.mozdev.popmungo.logger.debug('Submit '+ this.TOUR_FORM_NAME);
						tourForm.submit();
					}
				}
			}
		}
		catch (err) {
			org.mozdev.popmungo.logger.logError(err);
		}
	},
	
	
	autoSelectTransportDateAndTime:
	function autoSelectTransportDateAndTime(aDocument) {
		try {
			if (!org.mozdev.popmungo.prefs.isEnabled("extensions.popmungo.options.traveling.autoSelectTransportStartTime")) {
				return;
			}
			
			var lastRow = org.mozdev.popmungo.commonFunctions.XPathFirstNode(this.LAST_TRANSPORT_ROW_XPATH, aDocument);

			if (!lastRow) {
				return;
			}

			org.mozdev.popmungo.logger.debug(lastRow);

			var td1 = lastRow.cells.item(0);
			
			var dataMatch = td1.textContent.match(this.DATE_TIME_AND_CITY_NAME_ON_TRANSPORT_ROW_REGEXP);
			org.mozdev.popmungo.logger.debug(td1.textContent);
			
			if (dataMatch && dataMatch.length > 1) {
				var endDate = org.mozdev.popmungo.commonFunctions.trim(dataMatch[1]);
				var endTime = org.mozdev.popmungo.commonFunctions.trim(dataMatch[2]);
				//var city = org.mozdev.popmungo.commonFunctions.trim(dataMatch[3]);
				
				org.mozdev.popmungo.logger.debug('endDate='+ endDate +', endTime='+ endTime);
			
				var opt;
				var i;

				var movingDate = aDocument.getElementsByName(this.MOVING_DATE_NAME).item(0);
				
				for (i = movingDate.options.length - 1; i > -1; i--) {
					opt = movingDate.options.item(i);

					//org.mozdev.popmungo.logger.debug(i +': movingDate.text='+ opt.text);

					if (opt.text.match(endDate)) {
						org.mozdev.popmungo.logger.debug('movingDate.selectedIndex='+ i);
						
						movingDate.selectedIndex = i;

						break;
					}
				}					

				var movingTime = aDocument.getElementsByName(this.MOVING_TIME_NAME).item(0);
				
				for (i = movingTime.options.length - 1; i > -1; i--) {
					opt = movingTime.options.item(i);

					//org.mozdev.popmungo.logger.debug(i +': movingTime.text='+ opt.text);

					if (opt.text.match(endTime)) {
						org.mozdev.popmungo.logger.debug('movingTime.selectedIndex='+ i);
						
						movingTime.selectedIndex = i;

						break;
					}
				}					
			}
		}
		catch (err) {
			org.mozdev.popmungo.logger.logError(err);
		}
	},
	
	
	addCityNameToBusStationName: function addCityNameToBusStationName(aDocument) {
		try {
			var showMode = org.mozdev.popmungo.prefs.getPref(
				"extensions.popmungo.options.traveling.tourBusLocation.showCity.mode");

			if (showMode == 0) {
				return;
			}

			var linkNode = org.mozdev.popmungo.commonFunctions.XPathFirstNode(this.BUS_STATION_LINK_ON_CAREER_PAGE_XPATH, aDocument);
			
			if (linkNode) {
				var idMatch = linkNode.search.match(this.LOCALE_ID_REGEXP);
				
				if (!org.mozdev.popmungo.Charts.PrepareCities(aDocument)) {
					return;
				}				
				
				if (idMatch) {
					var localeId = idMatch[1];
					
					var cityId = org.mozdev.popmungo.busTerminals.getCityByBusTerminal(localeId);
					
					if (cityId) {
						var city = org.mozdev.popmungo.Charts.GetCityNameById(cityId); 
						
						if (city) {
							org.mozdev.popmungo.logger.debug("City="+ city);
							
							switch (showMode) {
								case 1:
									linkNode.appendChild(aDocument.createTextNode(", "+ city));
									break;
								case 2:
									// Remove the bus station name.
									while (linkNode.firstChild) {
										linkNode.removeChild(linkNode.firstChild);	
									}
									
									linkNode.appendChild(aDocument.createTextNode(city));
									break;
								default:
									org.mozdev.popmungo.logger.logError("Unsupported mode: "+ showMode);
							}
						}
						else {
							org.mozdev.popmungo.logger.debug("No city");
						}
					}
					else {
						org.mozdev.popmungo.logger.debug("No city ID.");
					}
				}
				else {
					org.mozdev.popmungo.logger.debug("Could not parse locale ID from URL.");
				}
			}
			else {
				org.mozdev.popmungo.logger.debug("No link node.");
			}
		}
		catch (err) {
			org.mozdev.popmungo.logger.logError(err);
		}
	}
};
